import random
from multiprocessing import Pipe

import pandas
from pyecharts.charts import Line, Bar, Pie, Scatter
from pyecharts import options as opts
from pyecharts.globals import ThemeType

from common.utils.thread.ThreadUtil import ThreadUtil
from common.utils.process.ProcessUtil import ProcessUtil
from qt.views.UIHomeView import *
from Ttsg_scrapy.main import crawlerProcess


class HomeController:
    def __init__(self):
        self.ui = UIHomeView()
        self.ui.show()
        self.ui.scrapyPBClickCallback = self.scrapyPBClickCallback
        self.ui.clearTablePBClickCallback = self.clearTablePBClickCallback
        self.ui.loadLocalDataPBClickCallback = self.loadLocalDataPBClickCallback
        self.ui.createChartPBClickCallback = self.createChartPBClickCallback

        self.process = ProcessUtil(config.log.statementShow)
        self.thread = ThreadUtil(config.log.statementShow)

        (self.pipes, self.piper) = Pipe()

        self.thread.startThread(self.phoneDatasRecv)

        self.original = []
        self.priceCount = None

    # region 委托
    def phoneDatasRecv(self):
        while True:
            data = self.piper.recv()
            self.original.append(data)
            self.ui.setTableUI(data)

    def analysePhonePriceCount(self, data):
        count = {"lower": 0, "medium": 0, "higher": 0}
        for item in data:
            price = item['price']
            if price < 2000:
                count['lower'] += 1
            elif price < 4000:
                count['medium'] += 1
            else:
                count['biger'] += 1
        self.phonePriceCount = count

    def analysePhoneBrondCount(self, data):
        count = {}
        for item in data:
            price = item['price']
            if price < 2000:
                count['lower'] += 1
            elif price < 4000:
                count['medium'] += 1
            else:
                count['biger'] += 1
        self.phonePriceCount = count
    # endregion

    # region 按钮点击回调
    def scrapyPBClickCallback(self, statue):
        if statue: self.process.startProcess(crawlerProcess, args=(self.pipes,))
        else: self.process.stopProcess()

    def clearTablePBClickCallback(self):
        self.original = []

    def loadLocalDataPBClickCallback(self):
        if not os.path.exists(f'{config.file.csvPath}{config.file.phoneDataFileName}.csv'):
            self.ui.printLog(f"无本地数据，导入失败！")
            return
        data = pandas.read_csv(f'{config.file.csvPath}{config.file.phoneDataFileName}.csv')
        data = eval(data.to_json(orient="records", force_ascii=False))
        self.original = data
        for item in data:
            self.ui.setTableUI(item)

    def createChartPBClickCallback(self, type):
        if self.original==None or len(self.original) == 0:
            self.ui.printLog(f"数据为空，无法生成图表！")
            return


        PieCount = analysePhonePricePieCount(self.original)
        pie_set_colors(PieCount['低端机'])
        pie_set_colors(PieCount['中端机'], "_2")
        pie_set_colors(PieCount['高端机'], "_3")

        priceCount, brondCount = analysePhonePriceCount(self.original, "play_memory")
        bar_base_dict_config(brondCount)
        scatter(brondCount)

        priceCount, brondCount = analysePhonePriceCount(self.original, "goods_memory")
        bar_base_dict_config(brondCount, "_2")
        scatter(brondCount, "_2")

        self.ui.setPyEchartUI()
    # endregion


def analysePhonePricePieCount(data):
    """
    根据手机价格统计手机数量
    :param data:
    :return:
    """
    count = {"低端机": {"安卓": [], "苹果": []}, "中端机": {"安卓": [], "苹果": []}, "高端机": {"安卓": [], "苹果": []}}
    for item in data:
        try:
            price = float(item['price'])
            title = item['goods_title']
        except Exception as e:
            print(e)
            continue
        if price < 1500:
            if "苹果" or "Apple" or "apple" in title:
                count['低端机']['苹果'].append(title)
            else:
                count['低端机']['安卓'].append(title)
        elif price < 3000:
            if "苹果" in title:
                count['中端机']['苹果'].append(title)
            else:
                count['中端机']['安卓'].append(title)
        else:
            if "苹果" in title:
                count['高端机']['苹果'].append(title)
            else:
                count['高端机']['安卓'].append(title)
    return count

def analysePhonePieCount(data, param):
    """
    根据商品某一属性统计商品数量
    :param data:
    :param param:
    :return:
    """
    count = {}
    for item in data:
        try:
            temp = item[param]
        except Exception as e:
            continue
        if temp in count:
            count[temp] += 1
        else:
            count[temp] = 1
    return count


def dictCountAdd1(data, key1, key2, value1):
    if key1 not in data.keys():
        data[key1] = value1.copy()
    if key2 in data[key1]:
        data[key1][key2] += 1
    else:
        data[key1][key2] = 1


def analysePhonePriceCount(data, param="brond"):
    """
    根据商品价格和商标统计数量
    :param data:
    :param param:
    :return:
    """
    priceCount = {"低端机": 0, "中端机": 0, "高端机": 0}
    defaultPriceCount = {"低端机": 0, "中端机": 0, "高端机": 0}
    brondCount = {}

    for item in data:
        try:
            price = float(item['price'])
            brond = item[param]
        except Exception as e:
            continue

        if price < 1500:
            key = '低端机'
            priceCount[key] += 1
            dictCountAdd1(brondCount, brond, key, defaultPriceCount)
        elif price < 3000:
            key = '中端机'
            priceCount[key] += 1
            dictCountAdd1(brondCount, brond, key, defaultPriceCount)
        else:
            key = '高端机'
            priceCount[key] += 1
            dictCountAdd1(brondCount, brond, key, defaultPriceCount)
    return priceCount, brondCount

def analysePhoneCount(data, params=['play_memory', 'price']):
    """
    根据商品任意两个属性统计商品数量
    :param data:
    :param params:
    :return:
    """
    count = {}

    for item in data:
        try:
            param1 = item[params[0]]
            param2 = item[params[1]]
        except Exception as e:
            continue

        if param1 not in count:
            count[param1] = []
        if param2 in count[param1]:
            count[param2].append(param2)

    return count

def pie_set_colors(data, id=""):
    """
    生成饼状图
    :param data:
    :return:
    """
    if type(data) == dict:
        data = [("苹果", len(data['苹果'])), ("安卓", len(data['安卓']))]
    pie = (
        Pie(init_opts=opts.InitOpts(theme=ThemeType.DARK))
        .add("", data)
        # .set_colors(["blue", "green", "yellow", "red", "pink","orange"])
        # .set_colors(["blue", "green", "yellow"])
        .set_global_opts(title_opts=opts.TitleOpts(title="饼图"+id))
    )
    pie.render(config.file.echartPath+config.file.pieFileName+id+".html")

def bar_base_dict_config(data, id=""):
    """
    生成柱状图
    :param data:
    :return:
    """
    if type(data) == dict:
        xaxis = list(data[list(data.keys())[0]].keys())
        yaxis = []
        for key in data.keys():
            yaxis.append({"key": key, "values": list(data[key].values())})
    else:
        xaxis = data['xaxis']
        yaxis = data['yaxis']
    bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK))
    bar.add_xaxis(xaxis)
    for item in yaxis:
        bar.add_yaxis(item["key"], item["values"])
    bar.set_global_opts(title_opts=opts.TitleOpts(title="柱状图"+id))
    bar.render(config.file.echartPath+config.file.barFileName+id+".html")

def line_base(data, id=""):
    """
    生成折线图
    :param data:
    :return:
    """
    if type(data) == dict:
        xaxis = list(data[list(data.keys())[0]].keys())
        yaxis = []
        for key in data.keys():
            yaxis.append({"key": key, "values": list(data[key].values())})
    else:
        xaxis = data['xaxis']
        yaxis = data['yaxis']

    line = Line(init_opts=opts.InitOpts(theme=ThemeType.DARK))
    line.add_xaxis(xaxis)
    for item in yaxis:
        line.add_yaxis(item["key"], item["values"])
    line.set_global_opts(title_opts=opts.TitleOpts(title="折线图"))

    line.render(config.file.echartPath+config.file.lineFileName+id+".html")

def scatter(data, id=""):
    """
    生成散点图
    :param data:
    :return:
    """
    if type(data) == dict:
        xaxis = list(data[list(data.keys())[0]].keys())
        yaxis = []
        for key in data.keys():
            yaxis.append({"key": key, "values": list(data[key].values())})
    else:
        xaxis = data['xaxis']
        yaxis = data['yaxis']

    scatter = Scatter(init_opts=opts.InitOpts(theme=ThemeType.DARK))
    scatter.add_xaxis(xaxis)
    for item in yaxis:
        scatter.add_yaxis(item["key"], item["values"])
    scatter.set_global_opts(title_opts=opts.TitleOpts(title="散点图"+id))
    scatter.render(config.file.echartPath+config.file.lineFileName+id+".html")

def pie_set_colors_plt(data):
    import numpy as np

    import matplotlib.pyplot as plt

    # 设置画布大小
    plt.figure(figsize=(10, 10))
    # 设置每块区域的标签
    labels = list(data.keys())
    # 设置每块区域离圆心的距离，这里a区域凸出一点点

    explode = [0.05]
    for i in range(1, len(data)):
        explode.append(0.01)
    # 设置每块区域的值
    values = list(data.values())

    _, l_text, p_text = plt.pie(values, explode=explode, labels=labels, autopct='%1.1f%%')

    # 设置标签字体大小
    for t in l_text:
        t.set_size(18)
    # 设置数值字体大小
    for t in p_text:
        t.set_size(18)

    # 标题
    plt.title(u'饼状图', fontsize=18)

    # 图例
    plt.legend(fontsize=18)

    # 保存图片
    plt.savefig(config.file.echartPath+config.file.pieFileName+'.pdf', bbox_inches='tight')
    # 显示图片
    plt.show()

def bar_base_dict_config_plt(data):
    if type(data) == dict:
        xaxis = list(data[list(data.keys())[0]].keys())
        yaxis = []
        for key in data.keys():
            yaxis.append({"key": key, "values": list(data[key].values())})
    else:
        xaxis = data['xaxis']
        yaxis = data['yaxis']

    import numpy as np
    import matplotlib.pyplot as plt

    # x轴刻度标签
    x_ticks = xaxis
    # 柱的宽度
    barWidth = 0.25

    # 设置画布大小
    plt.figure(figsize=(10, 6))
    # 第1个柱的x轴范围（每个柱子的中点）（0, 1, ..., len(x_ticks)-1）
    x0 = np.arange(len(x_ticks))
    x1 = x0
    for item in yaxis:
        x1 = [x + barWidth for x in x1]
        # 第1个柱数据
        y1 = item["values"]

        # 画第1个柱
        plt.bar(x1, y1, color='#FF0000', width=barWidth, label=item['key'])

        # 给第1个柱数据点加上数值，前两个参数是坐标，第三个是数值，ha和va分别是水平和垂直位置（数据点相对数值）。
        for a, b in zip(x1, y1):
            plt.text(a, b, '%d' % b, ha='center', va='bottom', fontsize=18)

    # 画水平横线
    plt.hlines(3, 0, len(x_ticks) - 1 + barWidth, colors="#000000", linestyles="dashed")

    # 添加x轴和y轴刻度标签
    plt.xticks([r + barWidth / 2 for r in x1], x_ticks, fontsize=18)
    plt.yticks(fontsize=18)

    # 添加x轴和y轴标签
    plt.xlabel(u'价格', fontsize=18)
    plt.ylabel(u'品牌', fontsize=18)

    # 标题
    plt.title(u'折线图', fontsize=18)

    # 图例
    plt.legend(fontsize=18)

    # 保存图片
    plt.savefig(config.file.echartPath+config.file.barFileName+'.pdf', bbox_inches='tight')
    # 显示图片
    plt.show()

def line_base_plt(data):
    if type(data) == dict:
        xaxis = list(data[list(data.keys())[0]].keys())
        yaxis = []
        for key in data.keys():
            yaxis.append({"key": key, "values": list(data[key].values())})
    else:
        xaxis = data['xaxis']
        yaxis = data['yaxis']

    import numpy as np
    import matplotlib.pyplot as plt

    # x轴刻度标签
    x_ticks = xaxis
    # x轴范围（0, 1, ..., len(x_ticks)-1）
    x = np.arange(len(x_ticks))
    # 设置画布大小
    plt.figure(figsize=(10, 6))
    for item in yaxis:
        # 画第1条折线，参数看名字就懂，还可以自定义数据点样式等等。
        plt.plot(x, item["values"], color='#FF0000', label=item["key"], linewidth=3.0)

        # 给第1条折线数据点加上数值，前两个参数是坐标，第三个是数值，ha和va分别是水平和垂直位置（数据点相对数值）。
        for a, b in zip(x, item["values"]):
            plt.text(a, b, '%d' % b, ha='center', va='bottom', fontsize=18)

    # 画水平横线，参数分别表示在y=3，x=0~len(x)-1处画直线。
    plt.hlines(3, 0, len(x) - 1, colors="#000000", linestyles="dashed")

    # 添加x轴和y轴刻度标签
    plt.xticks([r for r in x], x_ticks, fontsize=18, rotation=20)
    plt.yticks(fontsize=18)

    # 添加x轴和y轴标签
    plt.xlabel(u'价格范围', fontsize=18)
    plt.ylabel(u'手机品牌', fontsize=18)

    # 标题
    plt.title(u'折线图', fontsize=18)

    # 图例
    plt.legend(fontsize=18)

    # 保存图片
    plt.savefig(config.file.echartPath+config.file.lineFileName+'.pdf', bbox_inches='tight')
    print(config.file.echartPath+config.file.lineFileName+'.pdf')
    # 显示图片
    plt.show()


